home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 August: Technology Seed / ADC Seed CD - August 1999.toast / Carbon SDK 1.0d10c3 / Sample Code / SimpleText / PICTFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-04  |  27.0 KB  |  984 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        PICTFile.c
  3.  
  4.     Contains:    PICT file for simple text application
  5.  
  6.     Version:    SimpleText 1.4 or later
  7.  
  8.     Written by:    Tom Dowdy
  9.  
  10.     Copyright:    © 1993, 1995-1997 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Tom Dowdy
  15.  
  16.         Other Contact:        Jim Negrette
  17.  
  18.         Technology:            Macintosh Graphics Group
  19.  
  20.     Writers:
  21.  
  22.         (ecs)    Eric Schlegel
  23.         (dmp)    Dave Polaschek
  24.         (ted)    Tom Dowdy
  25.         (TD)    Tom Dowdy
  26.  
  27.     Change History (most recent first):
  28.  
  29.     $Log: PICTFile.c,v $
  30.     Revision 1.15  1999/05/01 01:52:24  jiarocci
  31.     Comment out grafprocs so we build against latest CarbonLib interfaces on 8.x.
  32.  
  33.     Revision 1.14  1999/02/16 00:41:39  christ
  34.     Integrate document proxy icon support
  35.  
  36.     Revision 1.13  1999/02/10 01:00:56  danp
  37.     Adding Andy Carroll's changes so we compile correctly on both X and MacOS 8.5
  38.     
  39.     Revision 1.12  1998/11/25 21:01:19  wilkes
  40.     Removed all GX references.
  41.     
  42.     Revision 1.11  1998/11/19 01:16:17  wilkes
  43.     Removed reliance on QuickTime.  Most changes were conditionalized with
  44.     ALLOW_QUICKTIME...
  45.  
  46.     Revision 1.10  1998/11/11 22:28:55  wilkes
  47.     Fixed various problems caused by the interface changes made by Nitin earlier,
  48.     mostly involving static RoutineDescriptors...
  49.  
  50.     Revision 1.9  1998/10/14 18:52:46  voas
  51.     Eliminate all warnings. Get working with top of tree.
  52.  
  53.     Revision 1.8  1998/10/12 18:50:56  danp
  54.     *** empty log message ***
  55.     
  56.     Revision 1.7  1998/09/15 18:59:46  jiarocci
  57.     SimpleText now builds with -DTARGET_CARBON=1. Still needs further cleanup.
  58.     
  59.     Revision 1.6  1998/09/02 20:43:17  danp
  60.     Minor changes so it'll compile with mwerks
  61.  
  62.  
  63.     Revision 1.5  1998/05/08 08:32:59  mkellner
  64.     Replaced another qd.arrow with GetQDarrow
  65.  
  66.     Revision 1.4  1998/03/30 22:12:28  mkellner
  67.     Update to use new GetQDxxxx macros for qd.globals
  68.     
  69.     Revision 1.3  1998/03/20 03:20:01  mkellner
  70.     change qd.thePort to FrontWindow()
  71.     add SysEnvirons
  72.     
  73.     Revision 1.2  1998/03/19 03:55:33  mkellner
  74.     - Add <ConditionalMacros.h> and <QTMLMapNames.h>
  75.     - Fix captialization of math.h, stdio.h, strings.h, etc.
  76.     - Change Types.h, Memory.h and Windows.h to MacTypes, MacMemory, and MacWindows
  77.     - Add inital set of stubs.
  78.     - Change Types.r to MacTypes.r
  79.     
  80.     Revision 1.1.1.1  1998/03/18 22:56:11  ivory
  81.     Initial checkin of SimpleText.
  82.     
  83.         
  84.         5     9/30/97 6:28 PM Sam Bushell
  85.         Added graphics importer support.
  86.         
  87.         4     8/20/97 4:24 PM Tom Dowdy
  88.         1674136: adjust cursor after select all
  89.         
  90.         3     7/30/97 4:32 PM Sam Bushell
  91.         Don't drag the selection if the click hit a control.
  92.         
  93.         2     7/29/97 2:06 PM Tom Dowdy
  94.         Removed all of the old and boring refs
  95.         
  96.         1     7/28/97 11:19 AM Duane Byram
  97.         first added to Source Safe project
  98.  
  99.         <13>     6/17/97    ted        Getting rid of some compiler warnings
  100.         <12>     5/14/97    ted        More drag clipping bug fixes
  101.         <11>     5/14/97    ted        More drag clipping bug fixes
  102.         <10>     12/5/96    ted        [1609760]  Watch cursor during open
  103.          <9>    11/26/96    ecs        smarter cursor adjustment
  104.          <8>      9/9/96    dmp        staticfy local functions to eliminate warnings in MWC.
  105.          <7>     5/31/96    ted        spelling FAT correctly
  106.          <7>     5/31/96    ted        adding PPC, FAT, and NuKernel builds
  107.          <6>    12/11/95    ted        fixing small windows on translation
  108.          <5>     11/2/95    ted        BlockMoveData
  109.          <4>    10/31/95    ted        fixing some pict resolutions
  110.          <3>    10/31/95    ted        adding support for high-res pict scaling
  111.          <2>     10/2/95    TD        adding support for SC compiler
  112.          <1>     8/21/95    TD        First checked in.
  113.  
  114. */
  115.  
  116. #include "MacIncludes.h"
  117.  
  118. #include "ImageCompression.h"
  119. // #include "GraphicsImporter.h"
  120.  
  121. #include "PICTFile.h"
  122.  
  123. /* ------------------------------------------------------------------------------------    */
  124. /* GLOBALS ONLY USED BY THIS FILE */
  125. /* ------------------------------------------------------------------------------------    */
  126. #define kBufferSize    2048
  127.  
  128. static short            gPictFileRefNum;
  129. static char                gPictureBuffer[kBufferSize];
  130. static long                gAmountInBuffer;
  131. static long                gFirstCharInBuffer;
  132. //static QDProcsPtr         gSavedProcs;
  133. static QDProcs            gMyProcs;
  134. static CQDProcs           gMyColorProcs;
  135.  
  136. // --------------------------------------------------------------------------------------------------------------
  137. // INTERNAL ROUTINES
  138. // --------------------------------------------------------------------------------------------------------------
  139.  
  140. static pascal void GetPICTData(Ptr dataPtr,short byteCount)
  141. /*
  142.     replacement for the QuickDraw bottleneck routine
  143. */
  144.     OSErr            err = noErr;
  145.     long            longCount;
  146.  
  147.     longCount = byteCount;
  148.     
  149.     while ( (longCount > 0) && (err == noErr) )
  150.         {
  151.         if (gAmountInBuffer == 0)
  152.             {
  153.             gAmountInBuffer = kBufferSize;
  154.             gFirstCharInBuffer = 0;
  155.             err = FSRead(gPictFileRefNum,&gAmountInBuffer,gPictureBuffer);
  156.             }
  157.  
  158.         if (gAmountInBuffer > 0)
  159.             {
  160.             long    amountToMove;
  161.             
  162.             amountToMove = gAmountInBuffer;
  163.             if (amountToMove > longCount)
  164.                 amountToMove = longCount;
  165.                 
  166.             BlockMoveData(&gPictureBuffer[gFirstCharInBuffer], dataPtr, amountToMove);
  167.             longCount -= amountToMove;
  168.             dataPtr += amountToMove;
  169.             gFirstCharInBuffer += amountToMove;
  170.             gAmountInBuffer -= amountToMove;
  171.             }
  172.             
  173.         }
  174.     
  175. } // GetPICTData
  176.  
  177.  
  178. // --------------------------------------------------------------------------------------------------------------
  179.  
  180. static OSErr    DiskPictureDraw( WindowDataPtr pData, 
  181.     Boolean doDraw, Rect *pictureRect, Point *pOffset)
  182. {
  183.  
  184.     OSErr        anErr;
  185.     PicHandle    picHandle;
  186.     Point        offset;
  187.     
  188.     if (pOffset)
  189.         offset = *pOffset;
  190.     else
  191.         {
  192.         offset.h = GetControlValue(pData->hScroll);
  193.         offset.v = GetControlValue(pData->vScroll);
  194.         }
  195.  
  196. #if ALLOW_QUICKTIME
  197.     if( ((PICTDataPtr)pData)->isQuickTimeImageFile )
  198.         {
  199.         GraphicsImportComponent theGraphicsImporter = 0;
  200.         
  201.         anErr = GetGraphicsImporterForFile( &pData->fileSpec, &theGraphicsImporter );
  202.         
  203.         if( noErr == anErr )
  204.             {
  205.             anErr = GraphicsImportSetQuality(
  206.                             theGraphicsImporter, 
  207.                             codecHighQuality );
  208.             }
  209.         
  210.         if( noErr == anErr )
  211.             {
  212.             Rect    destRect = ((PICTDataPtr)pData)->pictureRectangle;
  213.             
  214.             OffsetRect(&destRect, 
  215.                                 -destRect.left + 
  216.                                     pData->contentRect.left -
  217.                                     offset.h, 
  218.                                 -destRect.top + 
  219.                                     pData->contentRect.top -
  220.                                     offset.v);
  221.  
  222.             anErr = GraphicsImportSetBoundsRect( theGraphicsImporter, &destRect ); 
  223.             }
  224.         
  225.         if( noErr == anErr )
  226.             {
  227.             RgnHandle    theGripClip = NewRgn();
  228.             RectRgn( theGripClip, &pData->contentRect );
  229.             anErr = GraphicsImportSetClip( theGraphicsImporter, theGripClip );
  230.             DisposeRgn( theGripClip );
  231.             }
  232.         
  233.         if( noErr == anErr )
  234.             {
  235.             anErr = GraphicsImportDraw( theGraphicsImporter );
  236.             }
  237.         
  238.         if( 0 != theGraphicsImporter )
  239.             {
  240.             CloseComponent( theGraphicsImporter );
  241.             }
  242.         
  243.         return anErr;
  244.         }
  245. #endif
  246.  
  247.     picHandle = ((PICTDataPtr)pData)->cacheHandle;
  248.     
  249.     if (picHandle)
  250.         {
  251.  
  252.  
  253.         if (doDraw)
  254.             {
  255.             Rect    destRect;
  256.             
  257.             GetPICTRectangleAt72dpi(picHandle, &destRect);
  258.  
  259.             OffsetRect(&destRect, 
  260.                                 -destRect.left + 
  261.                                     pData->contentRect.left -
  262.                                     offset.h, 
  263.                                 -destRect.top + 
  264.                                     pData->contentRect.top -
  265.                                     offset.v);
  266.             DrawPicture(picHandle, &destRect);
  267.             }
  268.         
  269.         if (pictureRect)
  270.             {
  271.             GetPICTRectangleAt72dpi(picHandle, pictureRect);
  272.             OffsetRect(pictureRect, -pictureRect->left, -pictureRect->top);
  273.             }
  274.             
  275.         picHandle = nil;
  276.         anErr = noErr;
  277.         }
  278.     else
  279.         {
  280.         // make enough room for PICT header, including version
  281.         picHandle = (PicHandle) NewHandle(sizeof(Picture)  + sizeof(long)*8);
  282.         anErr = MemError();
  283.         nrequire(anErr, FailedNewHandle);
  284.         
  285.         gPictFileRefNum = pData->dataRefNum;
  286.         anErr = SetFPos(gPictFileRefNum, fsFromStart, 512);
  287.         nrequire(anErr, FailedSetFPos);
  288.         
  289.         gAmountInBuffer = kBufferSize;
  290.         gFirstCharInBuffer = 0;
  291.         anErr = FSRead(gPictFileRefNum, &gAmountInBuffer, gPictureBuffer);
  292.         if (anErr == eofErr)
  293.             anErr = noErr;
  294.         if (gAmountInBuffer < sizeof(Picture))
  295.             anErr = eofErr;
  296.         nrequire(anErr, FailedInitialRead);
  297.     
  298.         // copy PICT header, including version
  299.         BlockMoveData(gPictureBuffer, *picHandle, sizeof(Picture) + sizeof(long)*8);
  300.         gFirstCharInBuffer += sizeof(Picture);
  301.         gAmountInBuffer -= sizeof(Picture);
  302.         
  303.         if (doDraw)
  304.             {
  305.             Rect    destRect;
  306. #if USE_QD_GRAFPROCS
  307.             CGrafPtr thePort = GetQDGlobalsThePort();
  308. #endif
  309.             
  310.             GetPICTRectangleAt72dpi(picHandle, &destRect);
  311.             if (!gMachineInfo.haveQuickTime)
  312.                 {
  313.                 static QDGetPicUPP gGetPICTData = NULL;
  314. #if USE_QD_GRAFPROCS
  315.                 CQDProcs gprocs;
  316. #endif
  317.  
  318.                 if (!gGetPICTData) {
  319.                     gGetPICTData = NewQDGetPicProc(GetPICTData);
  320.                 }
  321.  
  322. #if USE_QD_GRAFROCS
  323.                 if (GetPortGrafProcs(thePort, &gprocs))
  324.                     SetPortGrafProcs(thePort, &gMyColorProcs);
  325.                 else
  326.                     SetStdCProcs(&gMyColorProcs);
  327. #endif
  328.                 gMyProcs.getPicProc = gGetPICTData;
  329.                 gMyColorProcs.getPicProc = gGetPICTData;
  330.                 }
  331.                 
  332.             OffsetRect(&destRect, -destRect.left +                         pData->contentRect.left - offset.h, 
  333.                 -destRect.top + pData->contentRect.top -
  334.                 offset.v);
  335.                                                 
  336.             if (!gMachineInfo.haveQuickTime)
  337.                 {
  338.                 DrawPicture(picHandle, &destRect);
  339.                 }
  340. #if ALLOW_QUICKTIME
  341.             else
  342.                 DrawPictureFile(gPictFileRefNum, &destRect, nil);
  343. #endif
  344.             }
  345.             
  346.         if (pictureRect)
  347.             {
  348.             GetPICTRectangleAt72dpi(picHandle, pictureRect);
  349.             OffsetRect(pictureRect, -pictureRect->left, 
  350.                     -pictureRect->top);
  351.             }
  352.         }
  353.     
  354. // FALL THROUGH EXCEPTION HANDLING
  355. FailedInitialRead:
  356. FailedSetFPos:
  357.     DisposeHandle((Handle) picHandle);
  358.  
  359. FailedNewHandle:
  360.     
  361.     return(anErr);
  362.         
  363. } // DiskPictureDraw
  364.  
  365. // --------------------------------------------------------------------------------------------------------------
  366. static OSErr GetSelectedPicture(WindowDataPtr pData, PicHandle *pResult)
  367. {
  368.     OSErr        anErr;
  369.     PicHandle    scrapPict;
  370.     Rect        globRect;
  371.     GDHandle    theMaxDevice;
  372.     short        theDepth;
  373.     GDHandle    savedGDevice;
  374.     CGrafPtr    savedPort;
  375.     GWorldPtr    offscreenGWorld;
  376.         RgnHandle    visRgn;
  377.     Rect        bounds;
  378.         PixMapHandle    bMap;
  379.  
  380.     // save away current value for restores
  381.     GetGWorld(&savedPort, &savedGDevice);
  382.  
  383.     // determine the best way in which to allocate stuff
  384.     
  385.     SetRect(&globRect, -32760, -32760, 32760, 32760);
  386.  
  387.     theDepth = 8;
  388.     theMaxDevice = GetMaxDevice(&globRect);
  389.     if (theMaxDevice != nil)
  390.         theDepth = (**(**theMaxDevice).gdPMap).pixelSize;
  391.     
  392.     // allocate the GWorld in temp mem, or local if we run out
  393.     anErr = NewGWorld(&offscreenGWorld, theDepth, 
  394.                         &((PICTDataPtr)pData)->selectionRectangle,
  395.                         nil, nil, useTempMem);
  396.     if (anErr != noErr)
  397.         anErr = NewGWorld(&offscreenGWorld, theDepth, 
  398.                             &((PICTDataPtr)pData)->selectionRectangle,
  399.                             nil, nil, 0);
  400.     nrequire(anErr, FailedNewGWorld);
  401.  
  402.     // blow open the visRgn, and clip to the selected area
  403.     visRgn = NewRgn();
  404.         GetPortVisibleRegion(offscreenGWorld, visRgn);
  405.     RectRgn(visRgn, &globRect);
  406.         DisposeRgn(visRgn);
  407.     PortChanged((GrafPtr) offscreenGWorld);
  408.     SetGWorld(offscreenGWorld, nil);
  409.     EraseRect(GetPortBounds(offscreenGWorld, &bounds));
  410.     ClipRect(&((PICTDataPtr)pData)->selectionRectangle);
  411.     
  412.     // Draw the picture into the offscreen
  413.     LockPixels( GetGWorldPixMap(offscreenGWorld));
  414.     {
  415.     Point    offset = {0,0};
  416.     anErr = DiskPictureDraw(pData, true, nil, &offset);
  417.     }
  418.     UnlockPixels( GetGWorldPixMap(offscreenGWorld));
  419.     nrequire(anErr, FailedDraw);
  420.  
  421.     // CopyBits in place to grab the selection
  422.     scrapPict = OpenPicture(&((PICTDataPtr)pData)->selectionRectangle);
  423.     LockPixels( GetGWorldPixMap(offscreenGWorld));
  424.         bMap = GetPortPixMap(offscreenGWorld);
  425.     CopyBits((BitMap *)*bMap, (BitMap *)*bMap, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->selectionRectangle, srcCopy, nil);
  426.     anErr = QDError();
  427.     UnlockPixels( GetGWorldPixMap(offscreenGWorld));
  428.     ClosePicture();
  429.     globRect = (**scrapPict).picFrame;
  430.     if ( (anErr == noErr) && (EmptyRect(&globRect)) )
  431.         anErr = memFullErr;
  432.         
  433.     // done with our offscreen now
  434.     SetGWorld(savedPort, savedGDevice);
  435.     DisposeGWorld(offscreenGWorld);
  436.  
  437.     if (anErr == noErr)
  438.         *pResult = scrapPict;
  439.     
  440.     return(anErr);
  441.     
  442. // EXCEPTION HANDLING
  443. FailedDraw:
  444.     DisposeGWorld(offscreenGWorld);
  445.     
  446. FailedNewGWorld:
  447.  
  448.     SetGWorld(savedPort, savedGDevice);
  449.     return(anErr);
  450.     
  451. } // GetSelectedPicture
  452.  
  453. // --------------------------------------------------------------------------------------------------------------
  454. static OSErr CopyGWorld(WindowDataPtr pData)
  455. {
  456.     OSErr        anErr;
  457.     PicHandle    scrapPict;
  458.  
  459.     anErr = GetSelectedPicture(pData, &scrapPict);
  460.  
  461.     if (anErr == noErr)
  462.         {
  463.         if (LoadScrap() == noErr)
  464.             {
  465.             ZeroScrap();
  466.             HLock((Handle) scrapPict);
  467.             anErr = PutScrap(GetHandleSize((Handle) scrapPict), 'PICT', (Ptr)*scrapPict);
  468.             KillPicture(scrapPict);
  469.             }
  470.         }
  471.     
  472.     return(anErr);
  473.     
  474. } // CopyGWorld
  475.  
  476. // --------------------------------------------------------------------------------------------------------------
  477. static pascal OSErr PICTSendDataProc(FlavorType theType, void *dragSendRefCon,
  478.                                 ItemReference theItem, DragReference theDrag)
  479. /*
  480.  *    The ItemReference is the gxShape to be sent. The dragSendRefCon is ignored.
  481. */
  482. {
  483. #pragma unused (theItem)
  484.  
  485.     OSErr    result = noErr;
  486.  
  487.     switch (theType) 
  488.         {
  489.         case 'PICT':
  490.             {    
  491.             PicHandle     pict;
  492.             OSErr        anErr = GetSelectedPicture((WindowDataPtr)dragSendRefCon, &pict);
  493.     
  494.             if (anErr == noErr)
  495.                 {    
  496.                 HLock((Handle)pict);
  497.                 result = SetDragItemFlavorData(theDrag, 1, 'PICT', (Ptr)*pict, GetHandleSize((Handle)pict), 0);
  498.                 KillPicture(pict);
  499.                 }
  500.             }
  501.             break;
  502.             
  503.         default:
  504.             result = badDragFlavorErr;
  505.             break;
  506.         }
  507.         
  508.     return result;
  509.     
  510. } // PICTSendDataProc
  511.  
  512.  
  513. // --------------------------------------------------------------------------------------------------------------
  514. // OOP INTERFACE ROUTINES
  515. // --------------------------------------------------------------------------------------------------------------
  516.  
  517. static OSErr    PICTUpdateWindow(WindowPtr pWindow, WindowDataPtr pData)
  518. {
  519.     OSErr        anErr;
  520.     RgnHandle    oldClip = NewRgn();
  521.     
  522.     EraseRect(&pData->contentRect);
  523.     
  524.     GetClip(oldClip);
  525.     ClipRect(&pData->contentRect);
  526.     anErr = DiskPictureDraw( pData, true, nil, nil);
  527.     SetClip(oldClip);
  528.     DisposeRgn(oldClip);
  529.     
  530.     DrawSelection(pData, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->patternPhase, false);
  531.     
  532.     DrawControls(pWindow);
  533.     DrawGrowIcon(pWindow);
  534.     
  535.     return(anErr);
  536.     
  537. } // PICTUpdateWindow
  538.  
  539. // --------------------------------------------------------------------------------------------------------------
  540.  
  541. static OSErr    PICTGetDocumentRect(WindowPtr pWindow, WindowDataPtr pData, 
  542.             LongRect * documentRectangle, Boolean forGrow)
  543. {
  544. #pragma unused (pWindow, forGrow)
  545.  
  546.     RectToLongRect(&((PICTDataPtr)pData)->pictureRectangle, documentRectangle);
  547.     
  548.     return(noErr);
  549.     
  550. } // PICTGetDocumentRect
  551.  
  552. // --------------------------------------------------------------------------------------------------------------
  553.  
  554. static OSErr    PICTCloseWindow(WindowPtr pWindow, WindowDataPtr pData)
  555. {
  556. #pragma unused (pWindow)
  557.  
  558.     DisposeHandle( (Handle) (((PICTDataPtr)pData)->cacheHandle));
  559.     
  560.     return(noErr);
  561.     
  562. } // PICTCloseWindow
  563.  
  564. // --------------------------------------------------------------------------------------------------------------
  565.  
  566. static OSErr    PICTContentClick(WindowPtr pWindow, WindowDataPtr pData, EventRecord *pEvent)
  567. {
  568.     OSErr            anErr = noErr;
  569.     Rect            selectionRect = ((PICTDataPtr)pData)->selectionRectangle;
  570.     Point            clickPoint = pEvent->where;
  571.     ControlHandle    theControl;
  572.     
  573.     GlobalToLocal(&clickPoint);
  574.     if (FindControl(clickPoint, pWindow, &theControl) == 0)
  575.         {
  576.         OffsetRect(&selectionRect, -GetControlValue(pData->hScroll), -GetControlValue(pData->vScroll));
  577.         if ( (gMachineInfo.haveDragMgr) && (PtInRect(clickPoint, &selectionRect)) )
  578.             {
  579.             DragAndDropArea(pWindow, pData, pEvent, 
  580.                                 &selectionRect);
  581.             }
  582.         else
  583.             {
  584.             anErr = SelectContents(pWindow, pData, pEvent, 
  585.                         &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->pictureRectangle, 
  586.                         &((PICTDataPtr)pData)->patternPhase);
  587.             }
  588.         }
  589.     
  590.     return(anErr);
  591.     
  592. } // PICTContentClick
  593.  
  594. // --------------------------------------------------------------------------------------------------------------
  595.  
  596. static OSErr    PICTAdjustCursor(WindowPtr pWindow, WindowDataPtr pData, Point * localMouse, RgnHandle globalRgn)
  597. {
  598. #pragma unused (pWindow)
  599.  
  600.     OSErr            anErr = noErr;
  601.     CursHandle        theCross;
  602.     Rect            selectionRect = ((PICTDataPtr)pData)->selectionRectangle;
  603.     Rect            globalSelection;
  604.     
  605.     OffsetRect(&selectionRect, -GetControlValue(pData->hScroll), -GetControlValue(pData->vScroll));
  606.     
  607.     globalSelection = selectionRect;
  608.     LocalToGlobal(&TopLeft(globalSelection));
  609.     LocalToGlobal(&BotRight(globalSelection));
  610.     
  611.     if (!PtInRect(*localMouse, &selectionRect) )
  612.         {
  613.         theCross = MacGetCursor(crossCursor);
  614.         if (theCross)
  615.             {
  616.             char    oldState;
  617.             
  618.             oldState = HGetState((Handle) theCross);
  619.             HLock((Handle) theCross);
  620.             SetCursor(*theCross);
  621.             HSetState((Handle) theCross, oldState);
  622.             anErr = eActionAlreadyHandled;
  623.             }
  624.             
  625.         // make sure we get mouse-moved events if the mouse moves into the selection rect,
  626.         // so that we can change the cursor
  627.         if (!EmptyRect(&globalSelection))
  628.             {    
  629.             RgnHandle    tempRgn = NewRgn();
  630.             
  631.             RectRgn(tempRgn, &globalSelection);
  632.             DiffRgn(globalRgn, tempRgn, globalRgn);
  633.             DisposeRgn(tempRgn);
  634.             }
  635.         }
  636.     else
  637.         {
  638.         // if we're already in the selection rect, we don't need mouse-moved events as long
  639.         // as we stay there
  640.         RectRgn(globalRgn, &globalSelection);
  641.         }
  642.         
  643.     return(anErr);
  644.     
  645. } // PICTAdjustCursor
  646.  
  647. // --------------------------------------------------------------------------------------------------------------
  648.  
  649. static OSErr    PICTDragAddFlavors(WindowPtr pWindow, WindowDataPtr pData, DragReference theDragRef)
  650. {
  651. #pragma unused (pWindow)
  652.  
  653.     static DragSendDataUPP gPICTSendDataProc = NULL;
  654.     OSErr    anErr = noErr;
  655.     
  656.     if (!gPICTSendDataProc) {
  657.         gPICTSendDataProc = NewDragSendDataProc(PICTSendDataProc);
  658.     }
  659.     SetDragSendProc(theDragRef, gPICTSendDataProc, pData);
  660.     AddDragItemFlavor(theDragRef, 1, 'PICT', nil, 0, 0);
  661.     
  662.     return(anErr);
  663.     
  664. } // PICTDragAddFlavors
  665.  
  666. // --------------------------------------------------------------------------------------------------------------
  667.  
  668. static OSErr    PICTGetBalloon(WindowPtr pWindow, WindowDataPtr pData, 
  669.         Point *localMouse, short * returnedBalloonIndex, Rect *returnedRectangle)
  670. {
  671. #pragma unused (pWindow, pData)
  672.  
  673.     Rect    tempRect = ((PICTDataPtr)pData)->selectionRectangle;
  674.     
  675.     // assume generic content
  676.     *returnedBalloonIndex = iHelpPictContent;
  677.     
  678.     // see if we are within the selection
  679.     OffsetRect(&tempRect, -GetControlValue(pData->hScroll), -GetControlValue(pData->vScroll) );
  680.     SectRect(&tempRect, &pData->contentRect, &tempRect);
  681.     
  682.     if (PtInRect(*localMouse, &tempRect))
  683.         {
  684.         *returnedRectangle        = tempRect;
  685.         *returnedBalloonIndex     = iHelpPictSelection;
  686.         }
  687.         
  688.     return(noErr);
  689.     
  690. } // PICTGetBalloon
  691.  
  692. // --------------------------------------------------------------------------------------------------------------
  693.  
  694. static OSErr    PICTPrintPage(WindowPtr pWindow, WindowDataPtr pData,
  695.                     Rect * pageRect, long *pageNum)
  696. {
  697. #pragma unused (pWindow)
  698.  
  699.     OSErr    anErr = noErr;
  700.     short    pagesWide, pagesHigh;
  701.     Rect    pictureRect = ((PICTDataPtr)pData)->pictureRectangle;
  702.     Point    offset;
  703.     Rect    localPageRect = *pageRect;
  704.     
  705.     // calculate how many physical pages will be required to print this PICT
  706.     if (EqualRect(&pictureRect, &localPageRect))
  707.         pagesWide = pagesHigh = 1;
  708.     else
  709.         {
  710.         pagesWide = (pictureRect.right - pictureRect.left) / (localPageRect.right - localPageRect.left) + 1;
  711.         pagesHigh = (pictureRect.bottom - pictureRect.top) / (localPageRect.bottom - localPageRect.top) + 1;
  712.         }
  713.                     
  714.     // compute the offset in # of pages
  715.     offset.h = ((*pageNum - 1) % pagesWide);
  716.     offset.v = ((*pageNum - 1) / pagesWide);
  717.  
  718.     // compute the pixel offset for this page
  719.     offset.h *= localPageRect.right - localPageRect.left;
  720.     offset.v *= localPageRect.bottom - localPageRect.top;
  721.     
  722.     anErr = DiskPictureDraw( pData, true, &localPageRect, &offset);
  723.     
  724.     // tell it to stop printing when we reach the end
  725.     if (*pageNum >= (pagesWide*pagesHigh))
  726.         *pageNum = -1;
  727.     
  728.     return(anErr);
  729.     
  730. } // PICTPrintPage
  731.  
  732. // --------------------------------------------------------------------------------------------------------------
  733.  
  734. static OSErr    PICTAdjustMenus(WindowPtr pWindow, WindowDataPtr pData)
  735. {
  736. #pragma unused (pWindow)
  737.  
  738.     OSErr anErr = noErr;
  739.     
  740.     if (!EmptyRect(&((PICTDataPtr)pData)->selectionRectangle))
  741.         EnableCommand(cCopy);
  742.  
  743.     if     (EqualRect(&((PICTDataPtr)pData)->pictureRectangle, &((PICTDataPtr)pData)->selectionRectangle))
  744.         ChangeCommandName(cSelectAll, kMiscStrings, iSelectNoneCommand);
  745.     else
  746.         ChangeCommandName(cSelectAll, kMiscStrings, iSelectAllCommand);
  747.     EnableCommand(cSelectAll);
  748.     
  749.     return(anErr);
  750.     
  751. } // PICTAdjustMenus
  752.  
  753. // --------------------------------------------------------------------------------------------------------------
  754.  
  755. static OSErr    PICTCommand(WindowPtr pWindow, WindowDataPtr pData, short commandID, long menuResult)
  756. {
  757. #pragma unused (pWindow, menuResult)
  758.  
  759.     OSErr    anErr = noErr;
  760.     
  761.     switch (commandID)
  762.         {
  763.         case cCopy:
  764.             anErr = CopyGWorld(pData);
  765.             break;
  766.         
  767.         case cSelectAll:
  768.             // erase the old selection
  769.             DrawSelection(pData, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->patternPhase, false);
  770.             
  771.             if     (EqualRect(&((PICTDataPtr)pData)->pictureRectangle, &((PICTDataPtr)pData)->selectionRectangle))
  772.                 {
  773.                 ((PICTDataPtr)pData)->selectionRectangle.top = 0;
  774.                 ((PICTDataPtr)pData)->selectionRectangle.left = 0;
  775.                 ((PICTDataPtr)pData)->selectionRectangle.bottom = 0;
  776.                 ((PICTDataPtr)pData)->selectionRectangle.right = 0;
  777.                 }
  778.             else
  779.                 {
  780.                 ((PICTDataPtr)pData)->selectionRectangle = ((PICTDataPtr)pData)->pictureRectangle;
  781.                 }
  782.                 
  783.             // draw the new selection
  784.             DrawSelection(pData, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->patternPhase, true);
  785.             
  786.             DoAdjustCursor(pWindow, nil);
  787.             break;
  788.         }
  789.     
  790.     return(anErr);
  791.     
  792. } // PICTCommand
  793.  
  794. // --------------------------------------------------------------------------------------------------------------
  795.  
  796. static long PICTCalculateIdleTime(WindowPtr pWindow, WindowDataPtr pData)
  797. {
  798. #pragma unused (pWindow)
  799.  
  800.     if (!EmptyRect( &((PICTDataPtr)pData)->selectionRectangle))
  801.         return(0);
  802.     else
  803.         return(kMaxWaitTime);
  804.         
  805. } // PICTCalculateIdleTime
  806.  
  807. // --------------------------------------------------------------------------------------------------------------
  808.  
  809. static Boolean    PICTFilterEvent(WindowPtr pWindow, WindowDataPtr pData, EventRecord *pEvent)
  810. {
  811.     if     (
  812.         (!gMachineInfo.amInBackground) &&
  813.         (pEvent->what == nullEvent) &&
  814.         (pWindow == FrontWindow()) &&
  815.         //(EmptyRgn( ((WindowPeek)pWindow)->updateRgn)) &&
  816.         (MOVESELECTION(pEvent->when) )
  817.         )
  818.         {
  819.         // erase the old
  820.         DrawSelection(pData, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->patternPhase, false);
  821.         
  822.         // draw the new, moving onto the next pattern
  823.         DrawSelection(pData, &((PICTDataPtr)pData)->selectionRectangle, &((PICTDataPtr)pData)->patternPhase, true);
  824.         }
  825.         
  826.     return(false);
  827.     
  828. } // PICTFilterEvent
  829.  
  830. // --------------------------------------------------------------------------------------------------------------
  831.  
  832. static OSErr    PICTMakeWindow(WindowPtr pWindow, WindowDataPtr pData)
  833. {
  834. #pragma unused (pWindow)
  835.  
  836.     Size    availableRAM;
  837.     long    amountInFile;
  838.     OSErr    anErr = noErr;
  839.     Cursor    arrow;
  840.  
  841.     pData->pUpdateWindow         = (UpdateWindowProc)        PICTUpdateWindow;
  842.     pData->pGetDocumentRect     = (GetDocumentRectProc)        PICTGetDocumentRect;
  843.     pData->pCloseWindow         = (CloseWindowProc)            PICTCloseWindow;
  844.     pData->pContentClick         = (ContentClickProc)        PICTContentClick;
  845.     pData->pAdjustCursor         = (AdjustCursorProc)        PICTAdjustCursor;
  846.     pData->pGetBalloon             = (GetBalloonProc)            PICTGetBalloon;
  847.     pData->pAdjustMenus         = (AdjustMenusProc)            PICTAdjustMenus;
  848.     pData->pPrintPage             = (PrintPageProc)            PICTPrintPage;
  849.     pData->pCommand                 = (CommandProc)                PICTCommand;
  850.     pData->pFilterEvent             = (FilterEventProc)            PICTFilterEvent;
  851.     pData->pCalculateIdleTime    = (CalculateIdleTimeProc)    PICTCalculateIdleTime;
  852.     pData->pDragAddFlavors        = (DragAddFlavorsProc)        PICTDragAddFlavors;
  853.  
  854.     pData->hasGrow                = true;
  855.     pData->hScrollAmount        = 10;
  856.     pData->vScrollAmount        = 10;
  857.  
  858.     ((PICTDataPtr)pData)->isQuickTimeImageFile = ( pData->originalFileType != 'PICT' );
  859. #if ALLOW_QUICKTIME
  860.     if( ((PICTDataPtr)pData)->isQuickTimeImageFile )
  861.         {
  862.         GraphicsImportComponent theGraphicsImporter;
  863.  
  864.         if (pData->dataRefNum != -1)
  865.             {
  866.             FSClose(pData->dataRefNum);
  867.             pData->dataRefNum = -1;
  868.             }
  869.  
  870.         SetPort( GetWindowPort(pWindow) );
  871.         anErr = GetGraphicsImporterForFile( &pData->fileSpec, &theGraphicsImporter );
  872.         if( noErr == anErr )
  873.             {
  874.             anErr = GraphicsImportGetNaturalBounds( theGraphicsImporter, &((PICTDataPtr)pData)->pictureRectangle );
  875.             CloseComponent( theGraphicsImporter );
  876.             }
  877.         }
  878.     else
  879. #endif
  880.     {
  881.         // Calculate amount of available RAM for cache
  882.         {
  883.             Size grow;
  884.             availableRAM = MaxMem(&grow);
  885.         }
  886.  
  887.         // Take half of it
  888.         availableRAM >>= 1;
  889.  
  890.         // if too big, make it just big enough
  891.         GetEOF(pData->dataRefNum, &amountInFile);
  892.         amountInFile -= 512;
  893.  
  894.         SetWatchCursor();
  895.  
  896.         if (amountInFile < sizeof(Picture))
  897.         {
  898.             anErr = eErrorWhileDrawing;
  899.         }
  900.         else
  901.         {
  902.             if (availableRAM > amountInFile)
  903.             {
  904.                 Handle    theHandle = NewHandle(amountInFile);
  905.  
  906.                 if (theHandle)
  907.                 {
  908.                     SetFPos(pData->dataRefNum, fsFromStart, 512);
  909.                     FSRead(pData->dataRefNum, &amountInFile, *theHandle);
  910.  
  911.                     ((PICTDataPtr)pData)->cacheHandle = (PicHandle)theHandle;
  912.                 }
  913.             }
  914.             
  915.             // initialize the rectangle to be valid
  916.             DiskPictureDraw( pData, false, &((PICTDataPtr)pData)->pictureRectangle, nil);
  917.  
  918.         }
  919.            SetCursor(GetQDGlobalsArrow(&arrow));
  920.     }
  921.     
  922.     if (anErr == noErr)
  923.     {
  924.         Rect    pictureRect;
  925.  
  926.         pictureRect = ((PICTDataPtr)pData)->pictureRectangle;
  927.  
  928.         if ((pData->contentRect.right > pictureRect.right) && (pictureRect.right > 0))
  929.             pData->contentRect.right = pictureRect.right;
  930.         if ((pData->contentRect.bottom > pictureRect.bottom) && (pictureRect.bottom > 0))
  931.             pData->contentRect.bottom = pictureRect.bottom;
  932.  
  933.         // proportional scrolling
  934.         if( gMachineInfo.haveProxyIcons )
  935.             {
  936.             SetControlViewSize( pData->hScroll, pictureRect.right - pictureRect.left );
  937.             SetControlViewSize( pData->vScroll, pictureRect.bottom - pictureRect.top );
  938.             }
  939.         }
  940.  
  941.     return(anErr);
  942.  
  943. } // PICTMakeWindow
  944.  
  945.  
  946. // --------------------------------------------------------------------------------------------------------------
  947.  
  948. OSErr    PICTPreflightWindow(PreflightPtr pPreflightData)
  949. {
  950.     pPreflightData->wantHScroll            = true;
  951.     pPreflightData->wantVScroll            = true;
  952.  
  953.     pPreflightData->continueWithOpen     = true;
  954.     pPreflightData->makeProcPtr         = PICTMakeWindow;
  955.  
  956.     pPreflightData->storageSize = sizeof(PICTDataRecord);
  957.  
  958.     return(noErr);
  959.  
  960. } // PICTPreflightWindow
  961.  
  962. // --------------------------------------------------------------------------------------------------------------
  963.  
  964. void PICTGetFileTypes(OSType * pFileTypes, OSType * pDocumentTypes, short * numTypes)
  965. {
  966. #if ALLOW_QUICKTIME
  967.     long version;    
  968. #endif
  969.  
  970.     pFileTypes[*numTypes]         = 'PICT';
  971.     pDocumentTypes[*numTypes]     = kPICTWindow;
  972.     (*numTypes)++;
  973.  
  974. #if ALLOW_QUICKTIME
  975.     if( (Gestalt(gestaltQuickTime, &version) == noErr) && (version >= 0x03000000) )
  976.         {
  977.         pFileTypes[*numTypes]         = 'qtif';
  978.         pDocumentTypes[*numTypes]     = kPICTWindow;
  979.         (*numTypes)++;
  980.         }
  981. #endif
  982. } // PICTGetFileTypes
  983.